home *** CD-ROM | disk | FTP | other *** search
/ Libris Britannia 4 / science library(b).zip / science library(b) / CUGUK / COMMS / C101.ZIP / UUPC11XT.ZIP / RN / RN.C < prev    next >
C/C++ Source or Header  |  1992-11-21  |  20KB  |  676 lines

  1. /*  rn -- new readnews program
  2.  *
  3.  *  Original Author: lwall@sdcrdcf.UUCP (Larry Wall)
  4.  *  Organization: System Development Corporation, Santa Monica
  5.  *
  6.  *  begun:   01/14/83
  7.  * 1.0: 04/08/83
  8.  *      2.0: 09/01/83
  9.  *      RRN/RN: 11/01/89
  10. */
  11.  
  12. static char rnid[] = "@(#)$Header: E:\SRC\UUPC\RN\RCS/RN.C 1.1 1992/11/21 06:14:58 ahd Exp $";
  13. static char patchlevel[] = "Patch #: 47";
  14.  
  15. /* $Log: RN.C $
  16.  * Revision 1.1  1992/11/21  06:14:58  ahd
  17.  * Initial
  18.  *
  19.  *
  20.  *    Rev 1.0   18 Nov 1990  0:22:04
  21.  * Initial revision.
  22.  * Revision 4.3.2.4  90/04/03  23:11:33  sob
  23.  * Added more information to the version command.
  24.  *
  25.  * Revision 4.3.2.3  90/03/22  23:05:23  sob
  26.  * Fixes provided by Wayne Davison <drivax!davison>
  27.  *
  28.  * Revision 4.3.2.2  89/11/28  01:51:25  sob
  29.  * Removed redundant #include directive.
  30.  *
  31.  * Revision 4.3.2.1  89/11/08  02:27:38  sob
  32.  * Release of RN 4.3 with RRN that can be compiled from the same
  33.  * sources as either version of the program.
  34.  *
  35.  * Revision 4.3.1.4  85/09/10  11:05:13  lwall
  36.  * Improved %m in in_char().
  37.  *
  38.  * Revision 4.3.1.3  85/05/16  16:47:10  lwall
  39.  * Catchup confirmation didn't grok -t.
  40.  *
  41.  * Revision 4.3.1.2  85/05/13  09:34:53  lwall
  42.  * Fixed default after do_newsgroup() returns from Q command.
  43.  *
  44.  * Revision 4.3.1.1  85/05/10  11:38:08  lwall
  45.  * Branch for patches.
  46.  *
  47.  * Revision 4.3  85/05/01  11:47:56  lwall
  48.  * Baseline for release with 4.3bsd.
  49.  *
  50.  */
  51.  
  52. #include "importng.h"
  53.  
  54. #include "INTERN.h"
  55. #include "common.h"
  56. #include "rn.h"
  57. #include "EXTERN.h"
  58. #include "rcstuff.h"
  59. #include "term.h"
  60. #include "final.h"
  61. #include "ngdata.h"
  62. #include "util.h"
  63. #include "only.h"
  64. #include "ngsrch.h"
  65. #include "help.h"
  66. #include "last.h"
  67. #include "init.h"
  68. #include "intrp.h"
  69. #include "rcln.h"
  70. #include "sw.h"
  71. #include "addng.h"
  72. #include "ng.h"
  73.  
  74. void rn_init(void);
  75. void set_ngname(char *what);
  76. char *getngdir(char *ngnam);
  77.  
  78. void
  79.   rn_init()
  80. {
  81.    ;
  82. }
  83.  
  84. void
  85.   main(argc, argv)
  86.    int argc;
  87.    char *argv[];
  88. {
  89.    bool foundany = initialize(argc, argv);
  90.    register char *s;
  91.    bool oh_for_the_good_old_days = FALSE;
  92.  
  93.    if (maxngtodo)
  94.       starthere = 0;
  95.    else if (!foundany)
  96.    {                         /* nothing to do? */
  97.  
  98. #ifdef VERBOSE
  99.       if (verbose)
  100.          fputs("\
  101. No unread news in subscribed-to newsgroups.  To subscribe to a new\n\
  102. newsgroup use the g<newsgroup> command.\n\
  103. ", stdout) FLUSH;
  104. #endif
  105.  
  106.       starthere = nextrcline;
  107.    }
  108.  
  109.    /* loop through all unread news */
  110.  
  111.    {
  112.       char promptbuf[80];
  113.       bool special = FALSE;  /* temporarily allow
  114.                               * newsgroup */
  115.  
  116.       /* with no unread news? */
  117.       bool retry;            /* cycle back to top of
  118.                               * list? */
  119.       NG_NUM recent_ng = 0;
  120.  
  121.       current_ng = 0;
  122.       do
  123.       {
  124.          retry = FALSE;
  125.          if (findlast)
  126.          {
  127.             findlast = FALSE;
  128.             starthere = 0;
  129.             if (*lastngname)
  130.             {
  131.                if ((ng = find_ng(lastngname)) == nextrcline)
  132.                   ng = 0;
  133.                else
  134.                {
  135.                   set_ngname(lastngname);
  136.                   set_toread(ng);
  137.                   if (toread[ng] <= TR_NONE)
  138.                      ng = 0;
  139.                }
  140.             }
  141.          }
  142.          else
  143.          {
  144.             ng = starthere;
  145.             starthere = 0;
  146.          }
  147.          while (ng <= nextrcline)
  148.          {                   /* for each newsgroup */
  149.             mode = 'n';
  150.             if (ng >= nextrcline)
  151.             {                /* after the last
  152.                               * newsgroup? */
  153.                ng = nextrcline; /* force it to 1 after */
  154.  
  155. #ifdef ONLY
  156.                if (maxngtodo)
  157.                {
  158.                   if (retry)
  159.  
  160. #ifdef VERBOSE
  161.                      IF(verbose)
  162.                         printf("\nRestriction %s%s still in effect.\n",
  163.                                ngtodo[0],
  164.                                maxngtodo > 1 ? ", etc." : nullstr) FLUSH;
  165.                   ELSE
  166. #endif
  167.  
  168. #ifdef TERSE
  169.                      fputs("\n(\"Only\" mode.)\n", stdout) FLUSH;
  170. #endif
  171.  
  172.                   else
  173.                   {
  174.  
  175. #ifdef VERBOSE
  176.                      IF(verbose)
  177.                         fputs("\nNo articles under restriction.",
  178.                               stdout) FLUSH;
  179.                      ELSE
  180. #endif
  181.  
  182. #ifdef TERSE
  183.                         fputs("\nNo \"only\" articles.", stdout) FLUSH;
  184. #endif
  185.  
  186.                      end_only();        /* release the
  187.                                          * restriction */
  188.                      retry = TRUE;
  189.                   }
  190.                }
  191. #endif
  192.  
  193.                dfltcmd = (retry ? "npq" : "qnp");
  194.  
  195. #ifdef VERBOSE
  196.                IF(verbose)
  197.                   sprintf(promptbuf,
  198.                           "\n******** End of newsgroups--what next? [%s] ",
  199.                           dfltcmd);
  200.                ELSE
  201. #endif
  202.  
  203. #ifdef TERSE
  204.                   sprintf(promptbuf,
  205.                           "\n**** End--next? [%s] ", dfltcmd);
  206. #endif
  207.             }
  208.             else
  209.             {
  210.                bool shoe_fits;  /* newsgroup matches
  211.                                  * restriction? */
  212.  
  213.                if (toread[ng] >= TR_NONE)
  214.                {             /* recalc toread? */
  215.                   set_ngname(rcline[ng]);
  216.                   if ((shoe_fits = (special || inlist(ngname))) != 0)
  217.                      set_toread(ng);
  218.                   if (paranoid)
  219.                   {
  220.                      recent_ng = current_ng;
  221.                      current_ng = ng;
  222.                      cleanup_rc();
  223.                      /* this may move newsgroups around */
  224.                      ng = current_ng;
  225.                      set_ngname(rcline[ng]);
  226.                   }
  227.                }
  228.                if (toread[ng] < (maxngtodo || special ? TR_NONE : TR_ONE) || !shoe_fits)
  229.                {
  230.                   /* unwanted newsgroup? */
  231.                   ng++;      /* then skip it */
  232.                   continue;
  233.                }
  234.          reprompt_newsgroup:
  235.                dfltcmd = "ynq";
  236.  
  237. #ifdef VERBOSE
  238.                IF(verbose)
  239.                   sprintf(promptbuf,
  240.                           "\n******** %3ld unread article%c in %s--read now? [%s] ",
  241.                           (long) toread[ng], (toread[ng] == TR_ONE ? ' ' : 's'),
  242.                           ngname, dfltcmd);     /* format prompt string */
  243.                ELSE
  244. #endif
  245.  
  246. #ifdef TERSE
  247.                   sprintf(promptbuf,
  248.                           "\n**** %3ld in %s--read? [%s] ",
  249.                           (long) toread[ng],
  250.                           ngname, dfltcmd);     /* format prompt string */
  251. #endif
  252.             }
  253.             special = FALSE; /* go back to normal
  254.                               * mode */
  255.             if (ng != current_ng)
  256.             {
  257.                recent_ng = current_ng;
  258.                /* remember previous newsgroup */
  259.                current_ng = ng; /* remember current
  260.                                  * newsgroup */
  261.             }
  262.       reask_newsgroup:
  263.             unflush_output();/* disable any ^O in
  264.                               * effect */
  265.             fputs(promptbuf, stdout) FLUSH;     /* print prompt */
  266.             fflush(stdout);
  267.       reinp_newsgroup:
  268.             eat_typeahead();
  269.             getcmd(buf);
  270.             if (errno || *buf == '\f')
  271.             {
  272.                putchar('\n') FLUSH;     /* if return from stop
  273.                                          * signal */
  274.                goto reask_newsgroup;    /* give them a prompt
  275.                                          * again */
  276.             }
  277.             setdef(buf, dfltcmd);
  278.  
  279. #ifdef VERIFY
  280.             printcmd();
  281. #endif
  282.  
  283.             switch (*buf)
  284.             {
  285.              case 'p':       /* find previous unread
  286.                               * newsgroup */
  287.                do
  288.                {
  289.                   if (ng <= 0)
  290.                      break;
  291.                   ng--;
  292.                   if (toread[ng] == TR_NONE)
  293.                      set_toread(ng);
  294.                } while (toread[ng] <= TR_NONE);
  295.                break;
  296.              case 'P':       /* goto previous
  297.                               * newsgroup */
  298.                do
  299.                {
  300.                   if (ng <= 0)
  301.                      break;
  302.                   ng--;
  303.                } while (toread[ng] < TR_NONE);
  304.                special = TRUE;  /* don't skip it if
  305.                                  * toread==0 */
  306.                break;
  307.              case '-':
  308.                ng = recent_ng;  /* recall previous
  309.                                  * newsgroup */
  310.                special = TRUE;  /* don't skip it if
  311.                                  * toread==0 */
  312.                break;
  313.              case 'q':
  314.              case 'Q':
  315.              case 'x':       /* quit? */
  316.                oh_for_the_good_old_days = (*buf == 'x');
  317.                putchar('\n') FLUSH;
  318.                ng = nextrcline + 1;     /* satisfy */
  319.                retry = FALSE;/* loop conditions */
  320.                break;
  321.              case '^':
  322.                putchar('\n') FLUSH;
  323.                ng = 0;
  324.                break;
  325.              case 'n':
  326.              case '+':       /* find next unread
  327.                               * newsgroup */
  328.                if (ng == nextrcline)
  329.                {
  330.                   putchar('\n') FLUSH;
  331.                   retry = TRUE;
  332.                }
  333.                else if (toread[ng] > TR_NONE)
  334.                   retry = TRUE;
  335.                ng++;
  336.                break;
  337.              case 'N':       /* goto next newsgroup */
  338.                ng++;
  339.                special = TRUE;  /* and don't skip it if
  340.                                  * toread==0 */
  341.                break;
  342.              case '1':       /* goto 1st newsgroup */
  343.                ng = 0;
  344.                special = TRUE;  /* and don't skip it if
  345.                                  * toread==0 */
  346.                break;
  347.              case '$':
  348.                ng = nextrcline; /* goto last newsgroup */
  349.                retry = TRUE;
  350.                break;
  351.              case 'L':
  352.                list_newsgroups();
  353.                goto reask_newsgroup;
  354.              case '/':
  355.              case '?':       /* scan for newsgroup
  356.                               * pattern */
  357.  
  358. #ifdef NGSEARCH
  359.                switch (ng_search(buf, TRUE))
  360.                {
  361.                 case NGS_ABORT:
  362.                   goto reinp_newsgroup;
  363.                 case NGS_INTR:
  364.  
  365. #ifdef VERBOSE
  366.                   IF(verbose)
  367.                      fputs("\n(Interrupted)\n", stdout) FLUSH;
  368.                   ELSE
  369. #endif
  370.  
  371. #ifdef TERSE
  372.                      fputs("\n(Intr)\n", stdout) FLUSH;
  373. #endif
  374.  
  375.                   ng = current_ng;
  376.                   goto reask_newsgroup;
  377.                 case NGS_FOUND:
  378.                   special = TRUE;       /* don't skip it if
  379.                                          * toread==0 */
  380.                   break;
  381.                 case NGS_NOTFOUND:
  382.  
  383. #ifdef VERBOSE
  384.                   IF(verbose)
  385.                      fputs("\n\nNot found--use g to add newsgroups\n",
  386.                            stdout) FLUSH;
  387.                   ELSE
  388. #endif
  389.  
  390. #ifdef TERSE
  391.                      fputs("\n\nNot found\n", stdout) FLUSH;
  392. #endif
  393.  
  394.                   goto reask_newsgroup;
  395.                }
  396. #else
  397.                notincl("/");
  398. #endif
  399.  
  400.                break;
  401.              case 'm':
  402.  
  403. #ifndef RELOCATE
  404.                notincl("m");
  405.                break;
  406. #endif
  407.  
  408.              case 'g':       /* goto named newsgroup */
  409.                if (!finish_command(FALSE))
  410.                   /* if they didn't finish command */
  411.                   goto reinp_newsgroup; /* go try something else */
  412.                for (s = buf + 1; *s == ' '; s++);
  413.                /* skip leading spaces */
  414.                if (!*s)
  415.                   strcpy(s, ngname);
  416.  
  417. #ifdef RELOCATE
  418.                if (!get_ng(s, *buf == 'm'))     /* try to find newsgroup */
  419. #else
  420.                if (!get_ng(s, FALSE))   /* try to find newsgroup */
  421. #endif
  422.  
  423.                   ng = current_ng;      /* if not found, go nowhere */
  424.                special = TRUE;  /* don't skip it if  toread==0 */
  425.                break;
  426.  
  427. #ifdef DEBUGGING
  428.              case 'D':
  429.                printf("\nTries: %d Hits: %d\n",
  430.                       softtries, softtries - softmisses) FLUSH;
  431.                goto reask_newsgroup;
  432. #endif
  433.  
  434.              case '!':       /* shell escape */
  435.                if (escapade())  /* do command */
  436.                   goto reinp_newsgroup;
  437.                /* if rubbed out, re input */
  438.                goto reask_newsgroup;
  439.              case Ctl('k'): /* edit global KILL file */
  440.                edit_kfile();
  441.                goto reask_newsgroup;
  442.              case 'c':       /* catch up */
  443.  
  444. #ifdef CATCHUP
  445.          reask_catchup:
  446.  
  447. #ifdef VERBOSE
  448.                IF(verbose)
  449.                   in_char("\nDo you really want to mark everything as read? [yn] ", 'C');
  450.                ELSE
  451. #endif
  452.  
  453. #ifdef TERSE
  454.                   in_char("\nReally? [ynh] ", 'C');
  455. #endif
  456.  
  457.                putchar('\n') FLUSH;
  458.                setdef(buf, "y");
  459.                if (*buf == 'h')
  460.                {
  461.  
  462. #ifdef VERBOSE
  463.                   printf("Type y or SP to mark all articles as read.\n");
  464.                   printf("Type n to leave articles marked as they are.\n");
  465. #else
  466.                   printf("y or SP to mark all read.\n");
  467.                   printf("n to forget it.\n");
  468. #endif
  469.  
  470.                   goto reask_catchup;
  471.                }
  472.                else if (*buf != ' ' && *buf != 'y' && *buf != 'n' && *buf != 'q')
  473.                {
  474.                   printf(hforhelp);
  475.                   settle_down();
  476.                   goto reask_catchup;
  477.                }
  478.                else if ((*buf == ' ' || *buf == 'y') && ng < nextrcline)
  479.                   catch_up(ng);
  480.                else
  481.                   retry = TRUE;
  482.                ng++;
  483. #else
  484.                notincl("c");
  485. #endif
  486.  
  487.                break;
  488.              case 'u':       /* unsubscribe */
  489.                if (ng < nextrcline && toread[ng] >= TR_NONE)
  490.                {
  491.                   /* unsubscribable? */
  492.                   printf(unsubto, rcline[ng]) FLUSH;
  493.                   rcchar[ng] = NEGCHAR;
  494.                   /* unsubscribe to (from?) it */
  495.                   toread[ng] = TR_UNSUB;
  496.                   /* and make line invisible */
  497.                   ng++;      /* do an automatic 'n' */
  498.                }
  499.                break;
  500.              case 'h':
  501.                {             /* help */
  502.                   int cmd;
  503.  
  504.                   if ((cmd = help_ng()) > 0)
  505.                      pushchar(cmd);
  506.                   goto reask_newsgroup;
  507.                }
  508.              case 'a':
  509.  
  510. #ifndef FINDNEWNG
  511.                notincl("a");
  512.                goto reask_newsgroup;
  513. #else
  514.                /* FALL THROUGH */
  515. #endif
  516.  
  517.              case 'o':
  518.  
  519. #ifdef ONLY
  520.                {
  521.  
  522. #ifdef FINDNEWNG
  523.                   bool doscan = (*buf == 'a');
  524.  
  525. #endif
  526.  
  527.                   if (!finish_command(TRUE))    /* get rest of command */
  528.                      goto reinp_newsgroup;      /* if rubbed out, try
  529.                                                  * something else */
  530.                   end_only();
  531.                   if (buf[1])
  532.                   {
  533.                      sw_list(buf + 1);
  534.                      cwd_check(FALSE);
  535.                      putchar('\n') FLUSH;
  536.  
  537. #ifdef FINDNEWNG
  538.                      if (doscan && maxngtodo)
  539.                         scanactive();
  540. #endif
  541.                   }
  542.                   ng = 0;    /* simulate ^ */
  543.                   retry = FALSE;
  544.                   break;
  545.                }
  546. #else
  547.                notincl("o");
  548.                goto reask_newsgroup;
  549. #endif
  550.  
  551.              case '&':
  552.                if (switcheroo())        /* get rest of command */
  553.                   goto reinp_newsgroup; /* if rubbed out, try
  554.                                          * something else */
  555.                goto reask_newsgroup;
  556.              case 'l':
  557.                {             /* list other newsgroups */
  558.                   if (!finish_command(TRUE))    /* get rest of command */
  559.                      goto reinp_newsgroup;      /* if rubbed out, try
  560.                                                  * something else */
  561.                   for (s = buf + 1; *s == ' '; s++);
  562.                   /* skip leading spaces */
  563.                   sprintf(cmd_buf, "%s '%s'", filexp(NEWSGROUPS), s);
  564.                   resetty();
  565.                   if (doshell(sh, cmd_buf))
  566.  
  567. #ifdef VERBOSE
  568.                      IF(verbose)
  569.                         fputs("    (Error from newsgroups program)\n",
  570.                               stdout) FLUSH;
  571.                   ELSE
  572. #endif
  573.  
  574. #ifdef TERSE
  575.                      fputs("(Error)\n", stdout) FLUSH;
  576. #endif
  577.  
  578.                   noecho();
  579.                   crmode();
  580.                   goto reask_newsgroup;
  581.                }
  582.              case '.':
  583.              case '=':
  584.              case 'y':
  585.              case 'Y':       /* do normal thing */
  586.                if (ng >= nextrcline)
  587.                {
  588.                   fputs("\nNot on a newsgroup.", stdout) FLUSH;
  589.                   goto reask_newsgroup;
  590.                }
  591.                if (*buf == '=')
  592.                   s = savestr("=");
  593.                else if (*buf == '.')
  594.                {             /* start command? */
  595.                   if (!finish_command(FALSE))   /* get rest of command */
  596.                      goto reinp_newsgroup;
  597.                   s = savestr(buf + 1);
  598.                   /* do_newsgroup will free it */
  599.                }
  600.                else
  601.                   s = Nullch;
  602.                if (toread[ng])
  603.                   retry = TRUE;
  604.                switch (do_newsgroup(s))
  605.                {
  606.                 case NG_ERROR:
  607.                 case NG_NORM:
  608.                   ng++;
  609.                   break;
  610.                 case NG_ASK:
  611.                   goto reprompt_newsgroup;
  612.                 case NG_MINUS:
  613.                   ng = recent_ng;       /* recall previous
  614.                                          * newsgroup */
  615.                   special = TRUE;       /* don't skip it if
  616.                                          * toread==0 */
  617.                   break;
  618.                }
  619.                break;
  620.  
  621. #ifdef STRICTCR
  622.              case '\n':
  623.                fputs(badcr, stdout) FLUSH;
  624.                goto reask_newsgroup;
  625. #endif
  626.  
  627.              case 'v':
  628.                printf("\n%s", rnid);
  629.                printf("\n%s", patchlevel);
  630.                printf("\nSend bugs to rrn@lib.tmc.edu\n") FLUSH;
  631.                goto reask_newsgroup;
  632.              default:
  633.                printf("\n%s", hforhelp) FLUSH;
  634.                settle_down();
  635.                goto reask_newsgroup;
  636.             }
  637.          }
  638.       } while (retry);
  639.    }
  640.  
  641.    /* now write .newsrc back out */
  642.  
  643.    write_rc();
  644.  
  645.    if (oh_for_the_good_old_days)
  646.       get_old_rc();
  647.  
  648.    finalize(0);              /* and exit */
  649. }
  650.  
  651. /*--------------------------------------------------------------------*/
  652. /*    s e t  _ n g n a m e                                            */
  653. /*                                                                    */
  654. /*    S e t   c u r r e n t   n e w s g r o u p                       */
  655. /*--------------------------------------------------------------------*/
  656.  
  657. void set_ngname(char *what)
  658. {
  659.    strcpy(ngname, what);
  660.    strcpy(ngdir, getngdir(what));
  661. }
  662.  
  663. /*--------------------------------------------------------------------*/
  664. /*    g e t n g d i r                                                 */
  665. /*                                                                    */
  666. /*    Set the news group directory from the news group name           */
  667. /*--------------------------------------------------------------------*/
  668.  
  669. char *getngdir(char *ngnam)
  670. {
  671.    static char myngdir[FILENAME_MAX];
  672.    register char *s;
  673.    ImportNewsGroup( myngdir, ngnam, 0 );
  674.    return myngdir;
  675. }
  676.